<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>

        const Pending = 'pending'
        const Fulfilled = 'fulfilled'
        const Rejected = 'rejected'

        class _Promise {
            constructor(fn) {
                this.state = Pending
                this.value = undefined
                this.reason = undefined
                this.resolveCallbackArr = []
                this.rejectCallbackArr = []

                let resolve = value => {
                    if (this.state === Pending) {
                        this.state === Fulfilled
                        this.value = value
                        this.resolveCallbackArr.forEach(callback => callback())
                    }
                }

                let reject = reason => {
                    if (this.state === Pending) {
                        this.state === Rejected
                        this.reason = reason
                        this.rejectCallbackArr.forEach(callback => callback())
                    }
                }

                fn(resolve, reject)
            }
            then(handleResolve, handleReject) {
                let p = new _Promise((resolve, reject) => {
                    let x
                    if (this.state === Fulfilled) {
                        setTimeout(() => {
                            x = handleResolve(this.value)
                            resolvePromise(p, x, resolve, reject)
                        }, 0)
                    }
                    if (this.state === Rejected) {
                        x = handleReject(this.reason)
                        resolvePromise(p, x, resolve, reject)
                    }
                    if (this.state === Pending) {
                        this.resolveCallbackArr.push(() => {
                            x = handleResolve(this.value)
                            resolvePromise(p, x, resolve, reject)
                        })
                        this.rejectCallbackArr.push(() => {
                            x = handleReject(this.value)
                            resolvePromise(p, x, resolve, reject)
                        })
                    }
                })
                return p
            }
        }

        function resolvePromise(p, x, resolve, reject) {
            if (p === x) {
                throw new Error('引用错误')
            }
            if ((x !== null && typeof x === 'object') || typeof x === 'function') {
                try {
                    let then = x.then
                    if (typeof then === 'function') {
                        then.call(x, value => { resolvePromise(p, value, resolve, reject) }, error => { reject(error) })
                    }
                } catch (err) {
                    reject(err)
                }
            } else {
                resolve(x)
            }
        }

        var p = new _Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(1)
            }, 1000)
        })

        p.then(result => console.log(1))

        p.then(result => {
            return new Promise()
        })

    </script>
</body>

</html>